/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gameheart.server;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicIntegerArray;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;

/**
 *
 * @author win7
 */
public class GameManager {
    int _passCarDirect = -1;
    ServerCard[] centerCards = new ServerCard[4];

    /**
     * @return the _recentlyDeal
     */
    public boolean isRecentlyDeal() {
        return _recentlyDeal;
    }
    /**
     * huong pass card
     */
    Direction _passCardDirection = Direction.Left;
    /**
     * quan bai cua 4 nguoi choi
     */
    List<List<ServerCard>> _cards = new ArrayList<List<ServerCard>>(4);

    /**
     * @return the _roundtripEnd
     */
    public boolean isRoundtripEnd() {
        return _roundtripEnd;
    }

    enum GameStateAfterPlayCard {

        RoundTripEnd, GameEnd, KetThucVanBai, NuocDiKhongHopLe, NuocDiDuocChapNhan, DealResquest
    };
    /**
     * nguoi choi bat dau vong choi.
     */
    int _firstUserId = -1;
    /**
     * so nguoi choi
     */
    public int playerNumber = 4;
    /**
     * userId cua nguoi choi dang co luot di
     */
    public int currentID = -1;
    /**
     * so diem trong van bai hien tai cua nguoi cho
     */
    private AtomicIntegerArray pointInHands = null;

    public GameManager() {
        int[] array = {0, 0, 0, 0};
        pointInHands = new AtomicIntegerArray(array);
        int[] totalPointArray = {0, 0, 0, 0};
        _totalPoints = new AtomicIntegerArray(totalPointArray);
    }
    /**
     * so diem trong toan tro choi cua nguoi choi.
     */
    private int[] totalMark = {0, 0, 0, 0};

    public synchronized int getPointInHand(int userId) {
        return pointInHands.get(userId);
    }
    volatile int _playedCardNumber = 0;
    AtomicIntegerArray _totalPoints;
    boolean firstCard = true;
    boolean canPlayCo = false;
    ServerCard _beginCard = new ServerCard(ServerCard.Type.Chuong, 1);
    boolean _havePlayedCo = false;
    private boolean isValid(int playerId, ServerCard card)
    {
        if(_playedCardNumber == 0 && card.compareTo(_beginCard) != 0 )
        {
            return false;
        }
        if(_havePlayedCo == false)
        {
            if(playerId == _firstUserId && card.getType() == ServerCard.Type.Co)
            {
                return false;
            }
        }
        if(playerId != _firstUserId && card.getType() != centerCards[_firstUserId].getType())
        {
           
            for(ServerCard playerCard : _cards.get(playerId))
            {
                if(playerCard.getType() == centerCards[_firstUserId].getType())
                {
                    return false;
                }
            }
        }
        return true;
        
        
    }
    private volatile  boolean  _roundtripEnd = false;
    /**
     * nguoi choi thuc hien nuoc di
     * @param playerID ma nguoi choi
     * @param card quan bang nguoi choi da di
     * @return true : nuoc di duoc chap nhan; false : nuoc di khong duoc chap nha
     */
    public synchronized GameStateAfterPlayCard playCard(int playerID, ServerCard card) {
        if(!isValid(playerID, card))
        {
            return GameStateAfterPlayCard.NuocDiKhongHopLe;
        }else
        {
            if(card.getType() == ServerCard.Type.Co || (card.getType() == ServerCard.Type.Bit && card.getDiem() == 11) )
            {
                _havePlayedCo = true;
            }
            for(ServerCard playerCard : _cards.get(playerID))
            {
                if(playerCard.compareTo(card) == 0)
                {
                    _cards.get(playerID).remove(playerCard);
                    break;
                }
            }
        }
        _roundtripEnd = false;
        GameStateAfterPlayCard result = GameStateAfterPlayCard.NuocDiDuocChapNhan;
        centerCards[playerID] = card;
        _playedCardNumber++;
        if (daDanhHetMotVong()) {
            _roundtripEnd = true;
            ServerCard beginCard = centerCards[_firstUserId];
            int maxCardUserId = _firstUserId;
            int soDiemTrongVongDanh = 0;
            for (int index = 0; index < centerCards.length; ++index) {
                if (centerCards[index].getType() == ServerCard.Type.Co) {
                    soDiemTrongVongDanh++;
                }
                if (centerCards[index].getType() == ServerCard.Type.Bit && centerCards[index].getDiem() == 11) {
                    soDiemTrongVongDanh = soDiemTrongVongDanh + 13;
                }
                if (centerCards[index].getType() == beginCard.getType()) {
                    if (centerCards[index].compareTo(centerCards[maxCardUserId]) > 0) {
                        maxCardUserId = index;
                    }
                }
            }
            ResetCenterCard();
            currentID = maxCardUserId;
            _firstUserId = currentID;
            pointInHands.set(maxCardUserId, pointInHands.get(maxCardUserId) + soDiemTrongVongDanh);
            if (_playedCardNumber == 52) {
                _handEnd = true;
                _playedCardNumber = 0;
                for (int index = 0; index < 4; ++index) {
                    _totalPoints.set(index, _totalPoints.get(index) + pointInHands.get(index));
                    pointInHands.set(index, 0);
                }
                _recentlyDeal = false;
            }
        } else {
            currentID = currentID + 1;
            currentID = currentID % 4;
        }
        System.out.println("Server : played card number :" + String.valueOf(_playedCardNumber));
        return result;

    }

    /**
     * lay userId cua nguoi choi dang co luot di
     * @return userId cua nguoi choi dang co luot di
     */
    public synchronized int getCurrentPlayerID() {
        return currentID;
    }

    /**
     * thuc hien viec chia bai
     * @return quan bai da chia. Moi dong tuong ung voi mot nguoi choi
     */
    public synchronized ServerCard[][] ChiaBai() {
        if(isRecentlyDeal())
        {
            return GetCards();

        }
        _passCarDirect ++;
        _passCardDirection = Direction.values()[_passCarDirect % 4];
        _havePlayedCo = false;
        _recentlyDeal = true;
        _playedCardNumber = 0;
        _passedUserNumber = 0;
        _handEnd = false;
        System.out.println("Server : handEnd = " + String.valueOf(_handEnd));
        ServerCard[][] cards = new ServerCard[4][13];
        ArrayList<ServerCard> boBais = new ArrayList<ServerCard>(52);
        for (int typeIndex = 0; typeIndex < 4; ++typeIndex) {
            for (int numberIndex = 0; numberIndex < 13; ++numberIndex) {
                ServerCard card = new ServerCard();
                card.setDiem(numberIndex);
                card.setType(ServerCard.Type.values()[typeIndex]);
                boBais.add(card);
            }
        }
        Random random = new Random();
        for (int rowIndex = 0; rowIndex < cards.length; ++rowIndex) {
            for (int columnIndex = 0; columnIndex < cards[0].length; ++columnIndex) {
                int cardIndex = random.nextInt(boBais.size());
                cards[rowIndex][columnIndex] = boBais.get(cardIndex);
                boBais.remove(cardIndex);

            }
        }
        _cards.clear();
        for (int indexPlayer = 0; indexPlayer < 4; ++indexPlayer) {
            _cards.add(new ArrayList<ServerCard>(Arrays.asList(cards[indexPlayer])));
        }
        return cards;
    }
    private boolean _recentlyDeal = false;
    boolean _handEnd = false;

    public synchronized boolean IsHandEnd() {
        System.out.println("Server : hand end" + String.valueOf(_handEnd));
        return _handEnd;
    }

    /**
     * lay quan bai cua cac nguoi choi
     * @return quan bai cua cac nguoi choi.
     */
    public synchronized ServerCard[][] GetCards() {
        ServerCard[][] result = new ServerCard[4][12];
        for (int index = 0; index < 4; ++index) {
            result[index] = _cards.get(index).toArray(result[index]);
            //System.out.println("quan bai duoc chia cho client  : ");
//            for (int tindex = 0; tindex < 13; ++tindex) {
////                if (cards[index].getDiem() == 0 && cards[index].getType() == CardServer.Type.Chuon) {
////                    luotdidautien = true;
////                }
//                System.out.println(String.valueOf(_cards.get(index).get(tindex).getDiem()) + ": " + _cards.get(index).get(tindex).getType().toString());
//            }
        }
        return result;
    }

    /**
     * lay huong pass card
     * @return huong pass card
     */
    public synchronized Direction getPassCardDirection() {
        return _passCardDirection;
    }

    /**
     * nguoi choi pass card
     * @param userId user id cua nguoi choi pass card
     * @param cards 3 quan bai nguoi choi pass
     * @return true : duoc chap nhat. false : khong duoc chap nhan
     */
    public synchronized boolean PassCard(int userId, ServerCard[] cards) {
        int tarUserId = -1;
        switch (_passCardDirection) {
            case Ahead: {
                tarUserId = userId + 2;
                break;
            }
            case Left: {
                tarUserId = userId + 1;
                break;
            }
            case Right: {
                tarUserId = userId + 3;
                break;
            }

        }
        tarUserId = tarUserId % 4;
        List<ServerCard> currentCard = _cards.get(userId);
        for (int passCardIndex = 0; passCardIndex < 3; ++passCardIndex) {
            for (int userCardIndex = 0; userCardIndex < currentCard.size(); ++userCardIndex) {
                if (currentCard.get(userCardIndex).compareTo(cards[passCardIndex]) == 0) {
                    currentCard.remove(userCardIndex);
                    break;
                }
            }
            _cards.get(tarUserId).add(cards[passCardIndex]);

        }
        ++_passedUserNumber;
        if (IsPassDone()) {
            for (int rowIndex = 0; rowIndex < _cards.size(); ++rowIndex) {
                for (int columnIndex = 0; columnIndex < _cards.get(rowIndex).size(); ++columnIndex) {
                    if (_cards.get(rowIndex).get(columnIndex).compareTo(_beginCard) == 0) {
                        currentID = rowIndex;
                        _firstUserId = currentID;
                    }
                }
            }
        }
        return true;
    }
    int _passedUserNumber = 0;

    public synchronized boolean IsPassDone() {

        if (_passedUserNumber % 4 == 0) {
            return true;
        }
        return false;
    }

    /**
     * lay quan bai da an cua nguoi choi. Chi tra ve co, dam bich
     * @param userID userId cua nguoi choi.
     * @return cac quan bai da an.
     */
    public synchronized ServerCard[] getQuanBaiDaAn(int userID) {
        throw new NotImplementedException();
    }
//    /**
//     * diem tong cong cac van bai cua nguoi choi
//     * @param userID userId cua nguoi choi
//     * @return so diem
//     */
//    public synchronized  int getDiemTongCong(int userID) {
//        throw new NotImplementedException();
//    }

    /**
     * diem tong cong cac van bai cua cac nguoi choi
     * @return so diem tong cong cua cac nguoi choi.
     */
    public synchronized int[] getDiemTongCongs() {
        int[] totalMarks = new int[4];
        for (int index = 0; index < 4; ++index) {
            totalMarks[index] = _totalPoints.get(index);
        }
        return totalMarks;
    }
    /**
     * kiem tra xem tat ca nguoi choi da thuc hien nuoc di chua
     * @return True :neu tat ca nguoi choi da thuc hien nuoc di; False : nguoc lai.
     */
    private synchronized boolean daDanhHetMotVong() {
        for (int index = 0; index < 4; ++index) {
            if (centerCards[index] == null) {
                return false;
            }
        }
        return true;
    }

    /**
     * kiem tra xem van bai da ket thuc chua.
     * Van bai ket thuc khi co nguoi choi dat diem toi da
     * @return true : neu van bai ket thuc. false : nguoc lai.
     */
    public synchronized boolean isEnd() {
        throw new NotImplementedException();
    }

//    public int isKiemTra() {
//        int maxIndex = 0;
//        CardServer cardOne = cardServerCenter[maxIndex];
//        for (int index = 1; index < cardServerCenter.length; index++) {
//            CardServer cardTemp = cardServerCenter[index];
//            if (cardTemp.getDiem() > cardOne.getDiem()
//                    && cardTemp.getType() == cardOne.getType()) {
//                maxIndex = index;
//            }
//        }
//        return maxIndex;
//    }
    public synchronized void ResetCenterCard() {
        for (int index = 0; index < centerCards.length; index++) {
            centerCards[index] = null;
        }
    }

}
